import { Button } from '@/components/ui/button';

import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/dialog';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Tabs, TabsContent } from '@/components/ui/tabs';
import config from '@/config';
import { useProxy } from '@/entrypoints/hook/useProxy';
import { saveFile } from '@/lib/filesystem';
import { getGigaSkuAndProductId, getProductPrice } from '@/lib/giga';
import {
  clearCatetoryAvaliable,
  getAvaliableDB,
  getCatetoryAvaliable,
  DB as gigaAvaliableDB,
} from '@/lib/gigaAvaliable';
import { confirmMessage } from '@/lib/imperative';
import { openDB, storeFileHandle } from '@/lib/indexedDb';
import { setProxyDirect } from '@/lib/proxy';
import { createButton } from '@/lib/utils';
import { useGigaStore } from '@/store/giga';
import { key, updateCateyoryTree, useGigaNotPersisStore } from '@/store/gigaNotPersist';
import { toast } from 'sonner';
import AvailableCollect from '../../components/AvailableCollect';
import AvailableSettings from './AvailableSetting';
import AvaliableLocalDiskInfo from './AvaliableLocalDiskInfo';
import { AvaliableOperation } from './AvaliableOperation';
import AvaliableReductionStatistics from './AvaliableReductionStatistics';
import AvaliableResume from './AvaliableResume';
import { GigaAvaliable } from './hook/useAvaliableDB';
import { useProxyStore } from '@/store/proxy';
import AvaliableReplenishmentStatistics from './AvaliableReplenishmentStatistics';
import AvaliableDayStatistics from './AvaliableDayChangeStatistics';

export default function AvaliableInfo() {
  const [open, setOpen] = useState(false);

  const categoryTree = useGigaNotPersisStore((state) => state.categoryTree);
  const selectedAvailableCategoryNames = useGigaNotPersisStore(
    (state) => state.selectedAvailableCategoryNames,
  );
  const dispatch = useGigaNotPersisStore((state) => state.dispatch);
  const currentAvailableCategoryName = useGigaNotPersisStore(
    (state) => state.currentAvailableCategoryName,
  );
  const currentTabValue = useGigaStore((state) => state.currentTabValue);
  const currentProxy = useProxyStore((state) => state.currentProxy);
  const proxyDispatch = useProxyStore((state) => state.dispatch);
  const gigaDispatch = useGigaStore((state) => state.dispatch);
  const isDefaultOpenAvaliable = useGigaStore(
    (state) => state.availableSettings.isDefaultOpenAvaliable,
  );
  const [categoryNames, setCategoryNames] = useState<string[]>([]);
  const { setFirstProxy } = useProxy(open);
  const [avaliableImportCount, setAvaliableImportCount] = useState(0);
  const [avaliableImportTotal, setAvaliableImportTotal] = useState(0);

  useEffect(() => {
    async function getCategoryNames() {
      const categoryNames = Object.keys(categoryTree).sort((categoryNameA, categoryNameB) => {
        return categoryNameA.localeCompare(categoryNameB);
      });

      setCategoryNames(categoryNames);
      if (!currentAvailableCategoryName && categoryNames.length > 0) {
        dispatch({
          type: 'update',
          update(draftState) {
            draftState.currentAvailableCategoryName = currentTabValue || categoryNames[0];
          },
        });
      }
    }
    getCategoryNames();
  }, [categoryTree]);

  // 点击查看库存详情
  useEffect(() => {
    let infoButton: HTMLButtonElement | null = document.querySelector('#avaliable-info');
    if (infoButton) {
      infoButton.remove();
    }
    infoButton = createButton('库存详情', 'custom-btn');
    infoButton.id = 'avaliable-info';
    document.body.appendChild(infoButton);
    infoButton.style.cssText = 'position: fixed; top: 10px; left: 120px; z-index: 1000';
    infoButton.addEventListener('click', () => {
      setOpen(true);
    });
  }, []);

  useEffect(() => {
    if (open) {
      document.body.style.overflow = 'hidden';
    } else {
      document.body.style.overflow = 'auto';
    }
  }, [open]);

  // 是否默认打开采集详情的弹框
  useEffect(() => {
    if (isDefaultOpenAvaliable) {
      setOpen(true);
    }
  }, [isDefaultOpenAvaliable]);

  const runTask = useCallback(async (skuInfo: string, timeStamp: number, db: gigaAvaliableDB) => {
    const [gigaSku, gigaProductId] = getGigaSkuAndProductId(skuInfo);
    let data = {} as Omit<GigaAvaliable, 'id'>;
    try {
      const result = await getProductPrice(gigaProductId);
      if (result.code === 200) {
        if (!result.data.qty_visible) {
          throw new Error('请先登录 giga 网站');
        }
        data = {
          skuInfo,
          timeStamp,
          // 对于非公开的产品,是没法获取库存数据的,这个时候把库存设置为 0
          avaliable: result.data?.quantity?.quantity || 0,
        };
        await db.gigaAvaliable.add(data);
      } else {
        throw new Error(`${result && result.msg}`);
      }
    } catch (error) {
      toast.error(`${skuInfo}: 获取库存失败 ${(error as Error).message}`, {
        position: 'top-right',
      });
      throw error;
    }
  }, []);

  async function fetchAllAvaliableWithQueue(categoryNames: string[]) {
    for (const categoryName of categoryNames) {
      const db = await getAvaliableDB(categoryName);
      const skuInfos = categoryTree[categoryName];
      dispatch({
        type: 'update',
        update(draftState) {
          draftState.availableConcurrent.currentCategoryName = categoryName;
        },
      });
      dispatch({
        type: 'clearAllQueue',
      });
      const timeStamp = Date.now();
      await Promise.all(
        skuInfos.map((skuInfo) => {
          return new Promise((resolve, reject) => {
            dispatch({
              type: 'enqueueTask',
              resolve,
              reject,
              task: {
                handleTask: async () => {
                  await runTask(skuInfo, timeStamp, db);
                },
                taskInfo: {
                  id: skuInfo,
                  skuIdInfo: skuInfo,
                  categoryName: categoryName,
                },
              },
            });
          });
        }),
      );
      toast.success(`完成 ${categoryName} 分类下的所有的产品获取操作`);
    }
  }

  async function fetchSelectedAvaliableWithQueue(categoryNames: string[]) {
    // console.log(selectedAvailableCategoryNames);
    const selectedCategoryNames = categoryNames.filter((categoryName) => {
      return selectedAvailableCategoryNames.includes(categoryName);
    });
    if (selectedCategoryNames.length === 0) {
      toast.info('请先选择需要处理的分类目录');
      return;
    }
    await fetchAllAvaliableWithQueue(selectedCategoryNames);
    toast.success('完成所有的选择的分类的产品获取操作');
  }

  return (
    <div>
      <div>
        <Dialog modal={false} open={open} onOpenChange={setOpen}>
          <DialogContent
            aria-describedby=""
            className="w-[90%] max-w-[1800px] h-[90vh] grid-rows-[auto_1fr]"
            style={{
              outline: `${open ? '9000px solid #000000e0' : 'none'}`,
              zIndex: config.dialogZIndex,
            }}
          >
            <DialogHeader>
              <div className="flex items-center">
                <DialogTitle className="text-card-foreground/80" id="">
                  giga 产品库存详情
                </DialogTitle>
                <Button
                  size="sm"
                  onClick={async () => {
                    await fetchAllAvaliableWithQueue(categoryNames);
                    toast.success('完成所有的分类产品获取操作');
                  }}
                  className="cursor-pointer ml-auto mr-3 hover:bg-[#337AB7] bg-[#428BCA]"
                >
                  获取所有分类库存
                </Button>
                <Button
                  size="sm"
                  onClick={async () => {
                    const jsonData = {} as Record<string, GigaAvaliable[]>;
                    const fileName = 'giga-库存.json';
                    await Promise.all(
                      categoryNames.map(async (categoryName) => {
                        const data = await getCatetoryAvaliable(categoryName);
                        // console.log(data);
                        jsonData[categoryName] = data;
                      }),
                    );
                    const dataText = JSON.stringify(jsonData);
                    toast.promise(saveFile(dataText, fileName), {
                      loading: '正在导出库存中...',
                      success: `成功导出库存到[${fileName}]文件中`,
                      error: '导出失败',
                    });
                  }}
                  className="cursor-pointer mr-3"
                >
                  导出所有库存
                </Button>
                <Button
                  size="sm"
                  onClick={async () => {
                    const fileHandle = await window.showOpenFilePicker();
                    const loadingId = toast.loading('正在导入库存');
                    try {
                      const avaliableFile = await fileHandle[0].getFile();
                      const avaliableJson = await avaliableFile.text();
                      const avaliable = JSON.parse(avaliableJson) as Record<
                        string,
                        GigaAvaliable[]
                      >;
                      // 关闭清空库存
                      // await Promise.all(
                      //   categoryNames.map((categoryName) => {
                      //     return clearCatetoryAvaliable(categoryName);
                      //   }),
                      // );

                      for (const categrotoryName of Object.keys(avaliable)) {
                        const db = await getAvaliableDB(categrotoryName);
                        const itemList = avaliable[categrotoryName];
                        setAvaliableImportTotal((prev) => prev + itemList.length);
                        for (const item of itemList) {
                          await db.gigaAvaliable.add(item);
                          setAvaliableImportCount((prev) => prev + 1);
                        }
                      }
                      // 不同的类目可以并行执行,因为使用不同的对象存储
                      // await Promise.all(
                      //   Object.keys(avaliable).map(async (categrotoryName) => {
                      //     const db = await getAvaliableDB(categrotoryName);
                      //     const itemList = avaliable[categrotoryName];
                      //     setAvaliableImportTotal((prev) => prev + itemList.length);
                      //     for (const item of itemList) {
                      //       await db.gigaAvaliable.add(item);
                      //       setAvaliableImportCount((prev) => prev + 1);
                      //     }
                      //   }),
                      // );
                      toast.success(`成功导入所有库存`);
                      toast.dismiss(loadingId);
                      setAvaliableImportTotal(0);
                      setAvaliableImportCount(0);
                    } catch (error) {
                      toast.error(`导入库存失败 ${(error as Error).message}`);
                      toast.dismiss(loadingId);
                    }
                    // clearCatetoryAvaliable
                  }}
                  className="cursor-pointer mr-3"
                >
                  导入所有库存
                  {avaliableImportTotal > 0 && `(${avaliableImportCount}/${avaliableImportTotal})`}
                </Button>
              </div>
            </DialogHeader>
            <div className="flex">
              <AvaliableLocalDiskInfo></AvaliableLocalDiskInfo>

              <Tabs value={currentTabValue} className="flex flex-col grow">
                {categoryNames.map((categoryName) => {
                  return (
                    <TabsContent
                      key={categoryName}
                      value={categoryName}
                      className="grow flex flex-col data-[state=inactive]:hidden"
                    >
                      <Card className="grow flex flex-col relative">
                        <CardHeader className="p-3">
                          <CardTitle className="text-base text-gray-700">{categoryName}</CardTitle>
                        </CardHeader>
                        <CardContent className="space-y-2 grow flex flex-col p-3">
                          <AvailableCollect
                            categoryName={categoryName}
                            skuInfos={categoryTree[categoryName]}
                            className="grow"
                          ></AvailableCollect>
                        </CardContent>
                      </Card>
                    </TabsContent>
                  );
                })}
                <TabsContent
                  value={config.gigaAvailableSettingsTabValue}
                  className="grow flex flex-col data-[state=inactive]:hidden"
                >
                  <Card className="grow flex flex-col relative">
                    <CardHeader>
                      <CardTitle className="text-base text-gray-700 flex items-center">
                        <span>库存采集设置</span>
                        <SettingsPersisted
                          store={useGigaStore}
                          className="ml-auto"
                          suggestedName="giga-settings.json"
                        ></SettingsPersisted>
                      </CardTitle>
                    </CardHeader>
                    <CardContent className="space-y-2 grow flex flex-col">
                      <AvailableSettings className="grow"></AvailableSettings>
                    </CardContent>
                  </Card>
                </TabsContent>
              </Tabs>
            </div>
            <div className="flex">
              <Button
                size={'sm'}
                onClick={async () => {
                  const directoryHandle = await window.showDirectoryPicker({
                    mode: 'readwrite',
                  });
                  dispatch({
                    type: 'update',
                    update(draftState) {
                      draftState.gigaRootDirectoryHandle = directoryHandle;
                      updateCateyoryTree(directoryHandle);
                      openDB().then((db) => {
                        storeFileHandle(directoryHandle, key, db);
                      });
                    },
                  });
                }}
                className="hover:bg-[#337AB7] bg-[#428BCA] mr-3"
              >
                设置分类根目录
              </Button>
              <Button
                size={'sm'}
                onClick={async () => {
                  await fetchSelectedAvaliableWithQueue(categoryNames);
                }}
                className="hover:bg-[#337AB7] bg-[#428BCA] mr-3"
              >
                批量获取分类库存
              </Button>
              <AvaliableReductionStatistics className="mr-3">
                <Button size={'sm'} className="hover:bg-[#337AB7] bg-[#428BCA]">
                  变化量统计
                </Button>
              </AvaliableReductionStatistics>
              <AvaliableReplenishmentStatistics className="mr-3">
                <Button size={'sm'} className="hover:bg-[#337AB7] bg-[#428BCA]">
                  补货量统计
                </Button>
              </AvaliableReplenishmentStatistics>
              <AvaliableDayStatistics className="mr-3">
                <Button size={'sm'} className="hover:bg-[#337AB7] bg-[#428BCA]">
                  变化天数统计
                </Button>
              </AvaliableDayStatistics>
              <Button
                onClick={async () => {
                  await setProxyDirect();
                  proxyDispatch({
                    type: 'update',
                    update(state) {
                      state.currentProxy = config.proxyDirectLabel;
                    },
                  });
                }}
                size={'sm'}
                className="hover:bg-[#337AB7] bg-[#428BCA] mr-3"
              >
                切换直连
              </Button>
              <Button
                onClick={async () => {
                  await setFirstProxy();
                }}
                size={'sm'}
                className="hover:bg-[#337AB7] bg-[#428BCA]"
              >
                切换代理({currentProxy})
              </Button>
              <Button
                size="sm"
                variant={'destructive'}
                onClick={async () => {
                  const isConfirm = await confirmMessage({
                    title: '清空库存数据',
                    description: '清空所有分类下的库存数据',
                    confirmText: '确定',
                    cancelText: '取消',
                  });
                  if (isConfirm) {
                    // 清空库存
                    await Promise.all(
                      categoryNames.map((categoryName) => {
                        return clearCatetoryAvaliable(categoryName);
                      }),
                    );
                    toast.success('清空成功', {
                      duration: 1500,
                    });
                  }
                }}
                className="cursor-pointer ml-auto mr-3"
              >
                清空所有的数据
              </Button>
            </div>
            <div className="flex" id="avaliable-collect-resume">
              <AvaliableOperation></AvaliableOperation>
              <AvaliableResume
                container={`#${'avaliable-collect-resume'}`}
                runTask={runTask}
              ></AvaliableResume>
            </div>
          </DialogContent>
        </Dialog>
      </div>
    </div>
  );
}
